<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=2"><meta name="theme-color" content="#FFF"><meta name="baidu-site-verification" content="code-DvHFUp3jdk"><meta name="baidu-site-verification" content="code-eHnRZZHAeP"><meta name="baidu-site-verification" content="code-EmlZBboqEW"><meta name="baidu-site-verification" content="code-Hf9ZXEHZ41"><meta name="360-site-verification" content="941073b91e9afaf02748ba000ba47e80"><meta name="360-site-verification" content="010bd45f0d523ce46f298dd597ef0289"><meta name="sogou_site_verification" content="hlLPNfmIjv"><meta name="sogou_site_verification" content="y3La2dTB20"><meta name="msvalidate.01" content="03829B28CC46A7AA4B5503897F475BA1"><script>!function(){var s="https://s.ssl.qhres2.com/ssl/ab77b6ea7f3fbf79.js";document.write('<script src="'+s+'" id="sozz"><\/script>')}()</script><script>!function(t,e,c,n,r,a,s){t[c]=t[c]||function(){(t[c].q=t[c].q||[]).push(arguments)},a=e.createElement(n),a.async=1,a.src="https://www.clarity.ms/tag/"+r+"?ref=bwt",s=e.getElementsByTagName(n)[0],s.parentNode.insertBefore(a,s)}(window,document,"clarity","script","8xwpfccwj2")</script><script>var _hmt=_hmt||[];!function(){var e=document.createElement("script");e.src="https://hm.baidu.com/hm.js?1d318b0509ca0909017253ed6f659ae4";var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t)}()</script><script>var _hmt=_hmt||[];!function(){var e=document.createElement("script");e.src="https://hm.baidu.com/hm.js?aea6c1471d6299bdd1c87a0836f18675";var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t)}()</script><script>var _hmt=_hmt||[];!function(){var e=document.createElement("script");e.src="https://hm.baidu.com/hm.js?498ca413655655a62058d6b5d7c62786";var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t)}()</script><script>var _hmt=_hmt||[];!function(){var e=document.createElement("script");e.src="https://hm.baidu.com/hm.js?e19e8161e13f718806b79f49240583b4";var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t)}()</script><link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon.png"><link rel="icon" type="image/ico" sizes="32x32" href="/images/favicon.ico"><meta http-equiv="Cache-Control" content="no-transform"><meta http-equiv="Cache-Control" content="no-siteapp"><meta name="google-site-verification" content="UA-139249935-1"><meta name="baidu-site-verification" content="cOtBu9CtTEIuwJeN"><link rel="alternate" type="application/rss+xml" title="了尘兰若的小坑" href="https://liaochenlanruo.gitee.io/rss.xml"><link rel="alternate" type="application/atom+xml" title="了尘兰若的小坑" href="https://liaochenlanruo.gitee.io/atom.xml"><link rel="alternate" type="application/json" title="了尘兰若的小坑" href="https://liaochenlanruo.gitee.io/feed.json"><link rel="stylesheet" href="//fonts.googleapis.com/css?family=Mulish:300,300italic,400,400italic,700,700italic%7CFredericka%20the%20Great:300,300italic,400,400italic,700,700italic%7CNoto%20Serif%20JP:300,300italic,400,400italic,700,700italic%7CNoto%20Serif%20SC:300,300italic,400,400italic,700,700italic%7CInconsolata:300,300italic,400,400italic,700,700italic&display=swap&subset=latin,latin-ext"><link rel="stylesheet" href="/css/app.css?v=0.2.5"><meta name="keywords" content="编程,Shiny入门系列"><link rel="canonical" href="https://liaochenlanruo.gitee.io/post/6718.html"><title>Shiny从入门到入定——6-布局、主题、HTML - IT | ResearchGo = 了尘兰若的小坑 = liaochenlanruo</title><meta name="generator" content="Hexo 5.4.0"></head><body itemscope itemtype="http://schema.org/WebPage"><div id="loading"><div class="cat"><div class="body"></div><div class="head"><div class="face"></div></div><div class="foot"><div class="tummy-end"></div><div class="bottom"></div><div class="legs left"></div><div class="legs right"></div></div><div class="paw"><div class="hands left"></div><div class="hands right"></div></div></div></div><div id="container"><header id="header" itemscope itemtype="http://schema.org/WPHeader"><div class="inner"><div id="brand"><div class="pjax"><h1 itemprop="name headline">Shiny从入门到入定——6-布局、主题、HTML</h1><div class="meta"><span class="item" title="Created: 2024-01-25 21:49:44"><span class="icon"><i class="ic i-calendar"></i> </span><span class="text">Posted on</span> <time itemprop="dateCreated datePublished" datetime="2024-01-25T21:49:44+08:00">2024-01-25</time> </span><span class="item" title="Symbols count in article"><span class="icon"><i class="ic i-pen"></i> </span><span class="text">Symbols count in article</span> <span>8.7k</span> <span class="text">words</span> </span><span class="item" title="Reading time"><span class="icon"><i class="ic i-clock"></i> </span><span class="text">Reading time</span> <span>8 mins.</span></span></div></div></div><nav id="nav"><div class="inner"><div class="toggle"><div class="lines" aria-label="Toggle navigation bar"><span class="line"></span> <span class="line"></span> <span class="line"></span></div></div><ul class="menu"><li class="item title"><a href="/" rel="start">ResearchGo</a></li></ul><ul class="right"><li class="item theme"><i class="ic i-sun"></i></li><li class="item search"><i class="ic i-search"></i></li></ul></div></nav></div><div id="imgs" class="pjax"><img src="https://cdn.jsdelivr.net/gh/liaochenlanruo/cdn@master/img/custom/bgs/thumb_206.webp"></div></header><div id="waves"><svg class="waves" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 24 150 28" preserveAspectRatio="none" shape-rendering="auto"><defs><path id="gentle-wave" d="M-160 44c30 0 58-18 88-18s 58 18 88 18 58-18 88-18 58 18 88 18 v44h-352z"/></defs><g class="parallax"><use xlink:href="#gentle-wave" x="48" y="0"/><use xlink:href="#gentle-wave" x="48" y="3"/><use xlink:href="#gentle-wave" x="48" y="5"/><use xlink:href="#gentle-wave" x="48" y="7"/></g></svg></div><main><div class="inner"><div id="main" class="pjax"><div class="article wrap"><div class="breadcrumb" itemscope itemtype="https://schema.org/BreadcrumbList"><i class="ic i-home"></i> <span><a href="/">Home</a></span><i class="ic i-angle-right"></i> <span class="current" itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem"><a href="/categories/IT/" itemprop="item" rel="index" title="In IT"><span itemprop="name">IT</span></a><meta itemprop="position" content="1"></span></div><article itemscope itemtype="http://schema.org/Article" class="post block" lang="en"><link itemprop="mainEntityOfPage" href="https://liaochenlanruo.gitee.io/post/6718.html"><span hidden itemprop="author" itemscope itemtype="http://schema.org/Person"><meta itemprop="image" content="/images/head.jpg"><meta itemprop="name" content="Hualin Liu"><meta itemprop="description" content="liaochenlanruo, 分享微生物生物信息学分析方法，欢迎加入QQ群交流945751012，不接受群内广告！"></span><span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization"><meta itemprop="name" content="了尘兰若的小坑"></span><div class="body md" itemprop="articleBody"><div class="gallery" itemscope itemtype="http://schema.org/ImageGallery"><img data-src="https://cdn.jsdelivr.net/gh/liaochenlanruo/cdn@master/img/custom/bgs/thumb_206.webp" itemprop="contentUrl"></div><h1 id="6-布局主题html"><a class="anchor" href="#6-布局主题html">#</a> 6 布局，主题，HTML</h1><ul><li>第 6 章详细介绍了在页面上布局输入和输出组件的各种方法，以及如何使用主题定制它们的外观。</li></ul><h2 id="61-前言"><a class="anchor" href="#61-前言">#</a> 6.1 前言</h2><p>在本章中，你将解锁一些控制应用程序整体外观的新工具。我们将首先讨论页面布局（包括单页和 “多页”），让你组织你的输入和输出。然后你将学习 Bootstrap，Shiny 使用的 CSS 工具包，以及如何用主题定制它的整体视觉外观。最后，我们将简要讨论一下幕后发生了什么，这样如果你知道 HTML 和 CSS，你就可以进一步定制 Shiny 应用程序。</p><figure class="highlight r"><figcaption data-lang="r"></figcaption><table><tr><td data-num="1"></td><td><pre>library<span class="token punctuation">(</span>shiny<span class="token punctuation">)</span></pre></td></tr></table></figure><h2 id="62-单页布局"><a class="anchor" href="#62-单页布局">#</a> 6.2 单页布局</h2><p>在第 2 章中，你学习了构成应用程序交互组件的输入和输出。但是我没有谈到如何在页面上布局它们，而是使用 <span class="exturl" data-url="aHR0cHM6Ly9yZHJyLmlvL3BrZy9zaGlueS9tYW4vZmx1aWRQYWdlLmh0bWw=">fluidPage()</span> 尽可能快地将它们拼凑在一起。虽然这对于学习 Shiny 来说是很好的，但它并不能创建可用或视觉上吸引人的应用程序，所以现在是时候学习一些更多的布局函数了。</p><p>布局功能提供了应用程序的高级视觉结构。布局由函数调用的层次结构创建，其中 R 中的层次结构与生成的 HTML 中的层次结构相匹配。这有助于您理解布局代码。例如，当您查看这样的布局代码时：</p><figure class="highlight r"><figcaption data-lang="r"></figcaption><table><tr><td data-num="1"></td><td><pre>fluidPage<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="2"></td><td><pre>  titlePanel<span class="token punctuation">(</span><span class="token string">"Hello Shiny!"</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="3"></td><td><pre>  sidebarLayout<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="4"></td><td><pre>    sidebarPanel<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="5"></td><td><pre>      sliderInput<span class="token punctuation">(</span><span class="token string">"obs"</span><span class="token punctuation">,</span> <span class="token string">"Observations:"</span><span class="token punctuation">,</span> min <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">,</span> max <span class="token operator">=</span> <span class="token number">1000</span><span class="token punctuation">,</span> value <span class="token operator">=</span> <span class="token number">500</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="6"></td><td><pre>    <span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="7"></td><td><pre>    mainPanel<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="8"></td><td><pre>      plotOutput<span class="token punctuation">(</span><span class="token string">"distPlot"</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="9"></td><td><pre>    <span class="token punctuation">)</span></pre></td></tr><tr><td data-num="10"></td><td><pre>  <span class="token punctuation">)</span></pre></td></tr><tr><td data-num="11"></td><td><pre><span class="token punctuation">)</span></pre></td></tr></table></figure><p>关注函数调用的层次结构：</p><figure class="highlight r"><figcaption data-lang="r"></figcaption><table><tr><td data-num="1"></td><td><pre>fluidPage<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="2"></td><td><pre>  titlePanel<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="3"></td><td><pre>  sidebarLayout<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="4"></td><td><pre>    sidebarPanel<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="5"></td><td><pre>    mainPanel<span class="token punctuation">(</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="6"></td><td><pre>  <span class="token punctuation">)</span></pre></td></tr><tr><td data-num="7"></td><td><pre><span class="token punctuation">)</span></pre></td></tr></table></figure><p>即使你还没有学习这些函数，通过阅读它们的名字，你也可以猜到发生了什么。你可能会想象这段代码会生成一个经典的应用程序设计：顶部有一个标题栏，后面是一个侧边栏（包含一个滑块）和主面板（包含一个绘图）。通过缩进轻松查看层次结构的能力是使用一致风格的一个好主意的原因之一。</p><p>在本节的剩余部分中，我将讨论帮助您设计单页应用程序的功能，然后在下一节中讨论多页应用程序。我还建议您查看 Shiny Application 布局指南；它有点过时，但包含一些有用的精华。</p><h3 id="621-页面功能"><a class="anchor" href="#621-页面功能">#</a> 6.2.1 页面功能</h3><p>最重要的，但最无趣的布局函数是 <span class="exturl" data-url="aHR0cHM6Ly9yZHJyLmlvL3BrZy9zaGlueS9tYW4vZmx1aWRQYWdlLmh0bWw=">fluidPage()</span>，到目前为止，您在几乎每个示例中都看到了它。但是它做了什么，如果单独使用它会怎么样？图 6.1 显示了结果：它看起来像一个非常无聊的应用程序，但幕后有很多事情，因为 <code>fluidPage()</code> 设置了 Shiny 所需的所有 HTML、CSS 和 JavaScript。</p><p><img data-src="https://d33wubrfki0l68.cloudfront.net/ad1d199cecafc2c2be10425930b1dcfb5e8dd5d7/1f5c9/images/action-layout/fluid-page.png" alt="图6.1 仅由 fluidPage() 构成的UI"></p><p>除了 <code>fluidPage()</code> ，Shiny 还提供了其他几个页面函数，在更特殊的情况下可以派上用场：<span class="exturl" data-url="aHR0cHM6Ly9yZHJyLmlvL3BrZy9zaGlueS9tYW4vZml4ZWRQYWdlLmh0bWw=">fixedPage()</span> 和<span class="exturl" data-url="aHR0cHM6Ly9yZHJyLmlvL3BrZy9zaGlueS9tYW4vZmlsbFBhZ2UuaHRtbA=="> fillPage ()</span>。 <code>fixedPage()</code> 的工作原理类似于 <code>fluidPage()</code> ，但有一个固定的最大宽度，可以防止你的应用程序在更大的屏幕上变得不合理地宽。 <code>fillPage()</code> 填充浏览器的整个高度，如果你想制作一个占据整个屏幕的图表，它很有用。你可以在他们的文档中找到详细信息。</p><h3 id="622-带侧边栏的页面"><a class="anchor" href="#622-带侧边栏的页面">#</a> 6.2.2 带侧边栏的页面</h3><p>要制作更复杂的布局，您需要在 <code>fluidPage()</code> 中调用布局函数。例如，要制作左侧有输入、右侧有输出的两列布局，可以使用 <span class="exturl" data-url="aHR0cHM6Ly9yZHJyLmlvL3BrZy9zaGlueS9tYW4vc2lkZWJhckxheW91dC5odG1s">sidebarLayout()</span>（以及它的朋友 <span class="exturl" data-url="aHR0cHM6Ly9yZHJyLmlvL3BrZy9zaGlueS9tYW4vdGl0bGVQYW5lbC5odG1s">titlePanel()</span>、 <span class="exturl" data-url="aHR0cHM6Ly9yZHJyLmlvL3BrZy9zaGlueS9tYW4vc2lkZWJhckxheW91dC5odG1s">sidebarPanel()</span> 和 <span class="exturl" data-url="aHR0cHM6Ly9yZHJyLmlvL3BrZy9zaGlueS9tYW4vc2lkZWJhckxheW91dC5odG1s">mainPanel()</span>）。以下代码显示了生成图 6.2 的基本结构：</p><figure class="highlight r"><figcaption data-lang="r"></figcaption><table><tr><td data-num="1"></td><td><pre>fluidPage<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="2"></td><td><pre>  titlePanel<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="3"></td><td><pre>    <span class="token comment"># app title/description</span></pre></td></tr><tr><td data-num="4"></td><td><pre>  <span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="5"></td><td><pre>  sidebarLayout<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="6"></td><td><pre>    sidebarPanel<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="7"></td><td><pre>      <span class="token comment"># inputs</span></pre></td></tr><tr><td data-num="8"></td><td><pre>    <span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="9"></td><td><pre>    mainPanel<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="10"></td><td><pre>      <span class="token comment"># outputs</span></pre></td></tr><tr><td data-num="11"></td><td><pre>    <span class="token punctuation">)</span></pre></td></tr><tr><td data-num="12"></td><td><pre>  <span class="token punctuation">)</span></pre></td></tr><tr><td data-num="13"></td><td><pre><span class="token punctuation">)</span></pre></td></tr></table></figure><p><img data-src="https://d33wubrfki0l68.cloudfront.net/37aa2b1c61a6141cc95188bffd0cfc782fdb27d5/b6aa6/diagrams/action-layout/sidebar.png" alt="图6.2 基础app的侧边栏结构"></p><p>为了让其更加真实，让我们增加一个输入和输出以创建一个演示中心极限定理的非常简单的应用程序，如图 6.3 所示。如果你自己运行这个应用程序，你可以增加样本数量以看到分布变得更加正常。</p><figure class="highlight r"><figcaption data-lang="r"></figcaption><table><tr><td data-num="1"></td><td><pre>ui <span class="token operator">&lt;-</span> fluidPage<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="2"></td><td><pre>  titlePanel<span class="token punctuation">(</span><span class="token string">"Central limit theorem"</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="3"></td><td><pre>  sidebarLayout<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="4"></td><td><pre>    sidebarPanel<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="5"></td><td><pre>      numericInput<span class="token punctuation">(</span><span class="token string">"m"</span><span class="token punctuation">,</span> <span class="token string">"Number of samples:"</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> min <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">,</span> max <span class="token operator">=</span> <span class="token number">100</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="6"></td><td><pre>    <span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="7"></td><td><pre>    mainPanel<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="8"></td><td><pre>      plotOutput<span class="token punctuation">(</span><span class="token string">"hist"</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="9"></td><td><pre>    <span class="token punctuation">)</span></pre></td></tr><tr><td data-num="10"></td><td><pre>  <span class="token punctuation">)</span></pre></td></tr><tr><td data-num="11"></td><td><pre><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="12"></td><td><pre>server <span class="token operator">&lt;-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>input<span class="token punctuation">,</span> output<span class="token punctuation">,</span> session<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span></pre></td></tr><tr><td data-num="13"></td><td><pre>  output<span class="token operator">$</span>hist <span class="token operator">&lt;-</span> renderPlot<span class="token punctuation">(</span><span class="token punctuation">&#123;</span></pre></td></tr><tr><td data-num="14"></td><td><pre>    means <span class="token operator">&lt;-</span> replicate<span class="token punctuation">(</span><span class="token number">1e4</span><span class="token punctuation">,</span> mean<span class="token punctuation">(</span>runif<span class="token punctuation">(</span>input<span class="token operator">$</span>m<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="15"></td><td><pre>    hist<span class="token punctuation">(</span>means<span class="token punctuation">,</span> breaks <span class="token operator">=</span> <span class="token number">20</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="16"></td><td><pre>  <span class="token punctuation">&#125;</span><span class="token punctuation">,</span> res <span class="token operator">=</span> <span class="token number">96</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="17"></td><td><pre><span class="token punctuation">&#125;</span></pre></td></tr></table></figure><p><img data-src="https://d33wubrfki0l68.cloudfront.net/4558a562a7be6b3c8bca4a25f3122d7322b536cc/6e6a0/demos/action-layout/sidebar.png" alt="图6.3 常见的应用程序设计是将控件放在侧边栏中，并将结果显示在主面板中"></p><h3 id="623-多行"><a class="anchor" href="#623-多行">#</a> 6.2.3 多行</h3><p>在幕后，<span class="exturl" data-url="aHR0cHM6Ly9yZHJyLmlvL3BrZy9zaGlueS9tYW4vc2lkZWJhckxheW91dC5odG1s">sidebarLayout()</span> 建立在灵活的多行布局之上，您可以直接使用它来创建更具视觉复杂性的应用程序。像往常一样，您从 <code>fluidPage()</code> 开始。然后，您使用<span class="exturl" data-url="aHR0cHM6Ly9yZHJyLmlvL3BrZy9zaGlueS9tYW4vZmx1aWRQYWdlLmh0bWw="> fluidRow ()</span> 创建行，使用<span class="exturl" data-url="aHR0cHM6Ly9yZHJyLmlvL3BrZy9zaGlueS9tYW4vY29sdW1uLmh0bWw="> column ()</span> 创建列。以下模板生成图 6.4 所示的结构：</p><figure class="highlight r"><figcaption data-lang="r"></figcaption><table><tr><td data-num="1"></td><td><pre>fluidPage<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="2"></td><td><pre>  fluidRow<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="3"></td><td><pre>    column<span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">,</span> </pre></td></tr><tr><td data-num="4"></td><td><pre>      <span class="token ellipsis">...</span></pre></td></tr><tr><td data-num="5"></td><td><pre>    <span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="6"></td><td><pre>    column<span class="token punctuation">(</span><span class="token number">8</span><span class="token punctuation">,</span> </pre></td></tr><tr><td data-num="7"></td><td><pre>      <span class="token ellipsis">...</span></pre></td></tr><tr><td data-num="8"></td><td><pre>    <span class="token punctuation">)</span></pre></td></tr><tr><td data-num="9"></td><td><pre>  <span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="10"></td><td><pre>  fluidRow<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="11"></td><td><pre>    column<span class="token punctuation">(</span><span class="token number">6</span><span class="token punctuation">,</span> </pre></td></tr><tr><td data-num="12"></td><td><pre>      <span class="token ellipsis">...</span></pre></td></tr><tr><td data-num="13"></td><td><pre>    <span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="14"></td><td><pre>    column<span class="token punctuation">(</span><span class="token number">6</span><span class="token punctuation">,</span> </pre></td></tr><tr><td data-num="15"></td><td><pre>      <span class="token ellipsis">...</span></pre></td></tr><tr><td data-num="16"></td><td><pre>    <span class="token punctuation">)</span></pre></td></tr><tr><td data-num="17"></td><td><pre>  <span class="token punctuation">)</span></pre></td></tr><tr><td data-num="18"></td><td><pre><span class="token punctuation">)</span></pre></td></tr></table></figure><p><img data-src="https://d33wubrfki0l68.cloudfront.net/15ea13e6dd0ba26014225718b5541abb983e0a45/7b30e/diagrams/action-layout/multirow.png" alt="图6.4 简单多行应用程序的基础结构"></p><p>每一行由 12 列组成， <code>column()</code> 的第一个参数给出了要占用的列数。12 列布局为您提供极大的灵活性，因为您可以轻松创建 2、3 或 4 列布局，或使用窄列创建间隔。您可以在第 4.4 节中看到这种布局的示例。</p><p>如果你想了解更多关于使用网格系统进行设计的知识，我强烈推荐由约瑟夫・穆勒 - 布罗克曼撰写的关于这个主题的经典文本：<span class="exturl" data-url="aHR0cHM6Ly93d3cuYW1hem9uLmNvbS9kcC8zNzIxMjAxNDUw">《平面设计中的网格系统》</span>。</p><h3 id="624-练习"><a class="anchor" href="#624-练习">#</a> 6.2.4 练习</h3><p><strong>6.2.4.1</strong> 阅读 <span class="exturl" data-url="aHR0cHM6Ly9yZHJyLmlvL3BrZy9zaGlueS9tYW4vc2lkZWJhckxheW91dC5odG1s">sidebarLayout()</span> 的文档，确定侧边栏和主面板的宽度（以列为单位）。你能使用 fluidRow () 和 column () 重新创建它的外观吗？你缺少什么？</p><p><strong>6.2.4.2</strong> 修改中心极限定理应用程序，将侧边栏放在右侧而不是左侧。</p><p><strong>6.2.4.3</strong> 创建一个包含两个图的应用程序，每个图占一半宽度。将控件放在图下方的全宽容器中。</p><h2 id="63-多页布局"><a class="anchor" href="#63-多页布局">#</a> 6.3 多页布局</h2><p>随着应用程序复杂性的增加，可能无法将所有内容都放在一个页面上。在本节中，您将学习 <span class="exturl" data-url="aHR0cHM6Ly9yZHJyLmlvL3BrZy9zaGlueS9tYW4vdGFiUGFuZWwuaHRtbA==">tabPanel()</span> 的各种用途，以创建多个页面的假象。这是一种假象，因为您仍然只有一个应用程序和一个基础 HTML 文件，但现在它被分解成多个部分，一次只能看到一个部分。</p><p>多页应用程序与模块搭配得特别好，你将在第 19 章了解模块。模块允许你以与划分用户界面相同的方式划分 server 函数，创建仅通过定义良好的连接进行交互的独立组件。</p><h3 id="631-选项卡集"><a class="anchor" href="#631-选项卡集">#</a> 6.3.1 选项卡集</h3><p>将页面分解成块的简单方法是使用 <span class="exturl" data-url="aHR0cHM6Ly9yZHJyLmlvL3BrZy9zaGlueS9tYW4vdGFic2V0UGFuZWwuaHRtbA==">tabsetPanel()</span> 及其亲密朋友 <code>tabPanel()</code> 。正如您在下面的代码中看到的， <code>tabsetPanel()</code> 为任意数量的 <code>tabPanels()</code> 创建一个容器，而 <code>tabPanels()</code> 反过来又包含任何其他 HTML 组件。图 6.5 显示了一个简单的例子。</p><figure class="highlight r"><figcaption data-lang="r"></figcaption><table><tr><td data-num="1"></td><td><pre>ui <span class="token operator">&lt;-</span> fluidPage<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="2"></td><td><pre>  tabsetPanel<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="3"></td><td><pre>    tabPanel<span class="token punctuation">(</span><span class="token string">"Import data"</span><span class="token punctuation">,</span> </pre></td></tr><tr><td data-num="4"></td><td><pre>      fileInput<span class="token punctuation">(</span><span class="token string">"file"</span><span class="token punctuation">,</span> <span class="token string">"Data"</span><span class="token punctuation">,</span> buttonLabel <span class="token operator">=</span> <span class="token string">"Upload..."</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="5"></td><td><pre>      textInput<span class="token punctuation">(</span><span class="token string">"delim"</span><span class="token punctuation">,</span> <span class="token string">"Delimiter (leave blank to guess)"</span><span class="token punctuation">,</span> <span class="token string">""</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="6"></td><td><pre>      numericInput<span class="token punctuation">(</span><span class="token string">"skip"</span><span class="token punctuation">,</span> <span class="token string">"Rows to skip"</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> min <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="7"></td><td><pre>      numericInput<span class="token punctuation">(</span><span class="token string">"rows"</span><span class="token punctuation">,</span> <span class="token string">"Rows to preview"</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">,</span> min <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="8"></td><td><pre>    <span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="9"></td><td><pre>    tabPanel<span class="token punctuation">(</span><span class="token string">"Set parameters"</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="10"></td><td><pre>    tabPanel<span class="token punctuation">(</span><span class="token string">"Visualise results"</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="11"></td><td><pre>  <span class="token punctuation">)</span></pre></td></tr><tr><td data-num="12"></td><td><pre><span class="token punctuation">)</span></pre></td></tr></table></figure><p><img data-src="https://d33wubrfki0l68.cloudfront.net/9c03ba6941047ea3face093a70f248673f4c824a/98580/demos/action-layout/tabset.png" alt="图6.5 tabsetPanel()允许用户选择单个tabPanel()进行查看"></p><p>如果您想知道用户选择了哪个选项卡，您可以将 <code>id</code> 参数提供给 <code>tabsetPanel()</code> 并将它设为输入。图 6.6 显示了这一点。</p><figure class="highlight r"><figcaption data-lang="r"></figcaption><table><tr><td data-num="1"></td><td><pre>ui <span class="token operator">&lt;-</span> fluidPage<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="2"></td><td><pre>  sidebarLayout<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="3"></td><td><pre>    sidebarPanel<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="4"></td><td><pre>      textOutput<span class="token punctuation">(</span><span class="token string">"panel"</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="5"></td><td><pre>    <span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="6"></td><td><pre>    mainPanel<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="7"></td><td><pre>      tabsetPanel<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="8"></td><td><pre>        id <span class="token operator">=</span> <span class="token string">"tabset"</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="9"></td><td><pre>        tabPanel<span class="token punctuation">(</span><span class="token string">"panel 1"</span><span class="token punctuation">,</span> <span class="token string">"one"</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="10"></td><td><pre>        tabPanel<span class="token punctuation">(</span><span class="token string">"panel 2"</span><span class="token punctuation">,</span> <span class="token string">"two"</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="11"></td><td><pre>        tabPanel<span class="token punctuation">(</span><span class="token string">"panel 3"</span><span class="token punctuation">,</span> <span class="token string">"three"</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="12"></td><td><pre>      <span class="token punctuation">)</span></pre></td></tr><tr><td data-num="13"></td><td><pre>    <span class="token punctuation">)</span></pre></td></tr><tr><td data-num="14"></td><td><pre>  <span class="token punctuation">)</span></pre></td></tr><tr><td data-num="15"></td><td><pre><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="16"></td><td><pre>server <span class="token operator">&lt;-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>input<span class="token punctuation">,</span> output<span class="token punctuation">,</span> session<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span></pre></td></tr><tr><td data-num="17"></td><td><pre>  output<span class="token operator">$</span>panel <span class="token operator">&lt;-</span> renderText<span class="token punctuation">(</span><span class="token punctuation">&#123;</span></pre></td></tr><tr><td data-num="18"></td><td><pre>    paste<span class="token punctuation">(</span><span class="token string">"Current panel: "</span><span class="token punctuation">,</span> input<span class="token operator">$</span>tabset<span class="token punctuation">)</span></pre></td></tr><tr><td data-num="19"></td><td><pre>  <span class="token punctuation">&#125;</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="20"></td><td><pre><span class="token punctuation">&#125;</span></pre></td></tr></table></figure><p><img data-src="https://d33wubrfki0l68.cloudfront.net/a856fa6a960d4e7e7b1cd2755c91934853e0e500/f7fbe/demos/action-layout/tabset-input-1.png" alt="图6.6 当您使用id参数时，tabset成为输入。这允许您根据当前可见的选项卡使您的应用程序表现不同。"></p><p>注意， <code>tabsetPanel()</code> 可以在应用程序中的任何地方使用；如果需要，将选项卡集嵌套在其他组件（包括选项卡集！）中是完全可以的。</p><h3 id="632-导航列表和导航栏"><a class="anchor" href="#632-导航列表和导航栏">#</a> 6.3.2 导航列表和导航栏</h3><p>因为标签是水平显示的，所以你可以使用的标签数量有一个基本的限制，特别是如果它们的标题很长。<span class="exturl" data-url="aHR0cHM6Ly9yZHJyLmlvL3BrZy9zaGlueS9tYW4vbmF2YmFyUGFnZS5odG1s">navbarPage()</span> 和<span class="exturl" data-url="aHR0cHM6Ly9yZHJyLmlvL3BrZy9zaGlueS9tYW4vbmF2YmFyUGFnZS5odG1s"> navbarMenu ()</span> 提供了两种替代布局，让你使用更多标签和更长的标题。</p><p><span class="exturl" data-url="aHR0cHM6Ly9yZHJyLmlvL3BrZy9zaGlueS9tYW4vbmF2bGlzdFBhbmVsLmh0bWw=">navlistPanel()</span> 类似于<span class="exturl" data-url="aHR0cHM6Ly9yZHJyLmlvL3BrZy9zaGlueS9tYW4vdGFic2V0UGFuZWwuaHRtbA=="> tabsetPanel ()</span>，但不会水平显示标签标题，而是在侧边栏中垂直显示。它还允许您使用纯字符串添加标题，如下面的代码所示，生成图 6.7。</p><figure class="highlight r"><figcaption data-lang="r"></figcaption><table><tr><td data-num="1"></td><td><pre>ui <span class="token operator">&lt;-</span> fluidPage<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="2"></td><td><pre>  navlistPanel<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="3"></td><td><pre>    id <span class="token operator">=</span> <span class="token string">"tabset"</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="4"></td><td><pre>    <span class="token string">"Heading 1"</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="5"></td><td><pre>    tabPanel<span class="token punctuation">(</span><span class="token string">"panel 1"</span><span class="token punctuation">,</span> <span class="token string">"Panel one contents"</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="6"></td><td><pre>    <span class="token string">"Heading 2"</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="7"></td><td><pre>    tabPanel<span class="token punctuation">(</span><span class="token string">"panel 2"</span><span class="token punctuation">,</span> <span class="token string">"Panel two contents"</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="8"></td><td><pre>    tabPanel<span class="token punctuation">(</span><span class="token string">"panel 3"</span><span class="token punctuation">,</span> <span class="token string">"Panel three contents"</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="9"></td><td><pre>  <span class="token punctuation">)</span></pre></td></tr><tr><td data-num="10"></td><td><pre><span class="token punctuation">)</span></pre></td></tr></table></figure><p><img data-src="https://d33wubrfki0l68.cloudfront.net/56785160c5b2c58ecebd5c89454f41ca8ba01132/3504e/demos/action-layout/navlistpanel.png" alt="图6.7 navlistPanel()垂直显示选项卡标题，而不是水平显示"></p><p>另一种方法是使用 <code>navbarPage()</code> ：它仍然产生水平选项卡标题，但您可以使用 <code>navbarMenu()</code> 添加下拉菜单以实现额外的层次结构。图 6.8 显示了一个简单的示例。</p><figure class="highlight r"><figcaption data-lang="r"></figcaption><table><tr><td data-num="1"></td><td><pre>ui <span class="token operator">&lt;-</span> navbarPage<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="2"></td><td><pre>  <span class="token string">"Page title"</span><span class="token punctuation">,</span>   </pre></td></tr><tr><td data-num="3"></td><td><pre>  tabPanel<span class="token punctuation">(</span><span class="token string">"panel 1"</span><span class="token punctuation">,</span> <span class="token string">"one"</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="4"></td><td><pre>  tabPanel<span class="token punctuation">(</span><span class="token string">"panel 2"</span><span class="token punctuation">,</span> <span class="token string">"two"</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="5"></td><td><pre>  tabPanel<span class="token punctuation">(</span><span class="token string">"panel 3"</span><span class="token punctuation">,</span> <span class="token string">"three"</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="6"></td><td><pre>  navbarMenu<span class="token punctuation">(</span><span class="token string">"subpanels"</span><span class="token punctuation">,</span> </pre></td></tr><tr><td data-num="7"></td><td><pre>    tabPanel<span class="token punctuation">(</span><span class="token string">"panel 4a"</span><span class="token punctuation">,</span> <span class="token string">"four-a"</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="8"></td><td><pre>    tabPanel<span class="token punctuation">(</span><span class="token string">"panel 4b"</span><span class="token punctuation">,</span> <span class="token string">"four-b"</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="9"></td><td><pre>    tabPanel<span class="token punctuation">(</span><span class="token string">"panel 4c"</span><span class="token punctuation">,</span> <span class="token string">"four-c"</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="10"></td><td><pre>  <span class="token punctuation">)</span></pre></td></tr><tr><td data-num="11"></td><td><pre><span class="token punctuation">)</span></pre></td></tr></table></figure><p><img data-src="https://d33wubrfki0l68.cloudfront.net/a2d6dc2e78a21f32db77925f1d28122e6288a44d/3c1ec/demos/action-layout/navbarpage.png" alt="图6.8 navbarPage()在页面顶部生成一个水平导航栏"></p><p>这些布局为你提供了相当大的能力来创建丰富而令人满意的应用程序。要更进一步，你需要更多地了解底层设计系统。</p><h2 id="64-引导程序bootstrap"><a class="anchor" href="#64-引导程序bootstrap">#</a> 6.4 引导程序（Bootstrap）</h2><p>要继续你的应用程序定制之旅，你需要更多地了解 Shiny 所使用的 <span class="exturl" data-url="aHR0cHM6Ly9nZXRib290c3RyYXAuY29tLw==">Bootstrap</span> 框架。Bootstrap 是一系列 HTML 约定、CSS 样式和 JS 代码片段的集合，打包成一种方便的形式。Bootstrap 最初是 Twitter 开发的一个框架，在过去的 10 年里，它已经发展成为网络上最流行的 CSS 框架之一。Bootstrap 在 R 中也很受欢迎 —— 你无疑已经看到过许多由 <span class="exturl" data-url="aHR0cHM6Ly9wa2dzLnJzdHVkaW8uY29tL3JtYXJrZG93bi9yZWZlcmVuY2UvaHRtbF9kb2N1bWVudC5odG1s">rmarkdown::html_document()</span> 生成的文档，并使用了许多由 <span class="exturl" data-url="aHR0cDovL3BrZ2Rvd24uci1saWIub3JnLw==">pkgdown</span> 制作的包网站，这两个网站也都使用了 Bootstrap。</p><p>作为 Shiny 开发人员，您不需要过多考虑 Bootstrap，因为 Shiny 会自动为您生成与 Bootstrap 兼容的 HTML。但是知道 Bootstrap 存在是件好事，因为这样：</p><ul><li><p>你可以使用<span class="exturl" data-url="aHR0cHM6Ly9yc3R1ZGlvLmdpdGh1Yi5pby9ic2xpYi9yZWZlcmVuY2UvYnNfdGhlbWUuaHRtbA=="> bslib::bs_theme ()</span> 来定制代码的视觉外观，第 6.5 节。</p></li><li><p>你可以使用 <code>class</code> 参数来使用 Bootstrap class 名定制一些布局、输入和输出，正如你在第 2.2.7 节中所看到的。</p></li><li><p>你可以自己编写函数来生成 Shiny 不提供的 Bootstrap 组件，如<span class="exturl" data-url="aHR0cHM6Ly9yc3R1ZGlvLmdpdGh1Yi5pby9ic2xpYi9hcnRpY2xlcy90aGVtaW5nLmh0bWwjdXRpbGl0eS1jbGFzc2Vz"> Utility classes</span> 中所述。</p></li></ul><p>也可以使用完全不同的 CSS 框架。许多现有的 R 包通过包装流行的 Bootstrap 替代品来简化这一过程：</p><ul><li><p><span class="exturl" data-url="aHR0cHM6Ly9hcHBzaWxvbi5jb20v">Appsilon</span> 构建在 <span class="exturl" data-url="aHR0cHM6Ly9mb21hbnRpYy11aS5jb20v">formantic UI</span> 之上的<span class="exturl" data-url="aHR0cHM6Ly9hcHBzaWxvbi5naXRodWIuaW8vc2hpbnkuc2VtYW50aWMv"> shiny.semantic</span>。</p></li><li><p><span class="exturl" data-url="aHR0cHM6Ly9yaW50ZXJmYWNlLmNvbS8=">RInterface</span> 基于 <span class="exturl" data-url="aHR0cHM6Ly9mcmFtZXdvcms3LmlvLw==">framework 7</span> 构建的 <span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL1JpbnRlUmZhY2Uvc2hpbnlNb2JpbGU=">shinyMobile</span> ，专为移动应用程序而设计。</p></li><li><p>由 <span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL2VyaWNyYXlhbmRlcnNvbg==">Eric Anderson</span> 开发的 <span class="exturl" data-url="aHR0cHM6Ly9lcmljcmF5YW5kZXJzb24uZ2l0aHViLmlvL3NoaW55bWF0ZXJpYWwv">shinymaterial</span>，建立在谷歌的 <span class="exturl" data-url="aHR0cHM6Ly9tYXRlcmlhbC5pby9kZXNpZ24=">Material</span> 设计框架之上。</p></li><li><p><span class="exturl" data-url="aHR0cHM6Ly9yc3R1ZGlvLmdpdGh1Yi5pby9zaGlueWRhc2hib2FyZC8=">shinydashboard</span> 也是由 RStudio 开发的，它提供了一个用于创建仪表板的布局系统。</p></li></ul><p>你可以在 <span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL25hbnhzdGF0cy9hd2Vzb21lLXNoaW55LWV4dGVuc2lvbnM=">https://github.com/nanxstats/awesome-shiny-extensions</span> 上找到一个更完整、维护更活跃的列表。</p><h2 id="65-主题"><a class="anchor" href="#65-主题">#</a> 6.5 主题</h2><p>Bootstrap 在 R 社区中无处不在，很容易让人产生审美疲劳：过了一段时间，每个 Shiny 应用程序和 Rmd 看起来都差不多。解决方案是使用<span class="exturl" data-url="aHR0cHM6Ly9yc3R1ZGlvLmdpdGh1Yi5pby9ic2xpYg=="> bslib</span> 包进行主题化。bslib 是一个相对较新的包，允许您覆盖许多 Bootstrap 默认值，以创建独特的外观。在我写这篇文章的时候，bslib 主要适用于 Shiny，但正在努力将其增强的主题化功能引入 RMarkdown、pkgdown 等。</p><p>如果你正在为公司开发应用程序，我强烈建议你花点时间在主题化上 —— 将你的应用程序主题化，以匹配你的企业风格指南，这是一种让你看起来很好的简单方法。</p><h3 id="651-开始"><a class="anchor" href="#651-开始">#</a> 6.5.1 开始</h3><p>使用 <span class="exturl" data-url="aHR0cHM6Ly9yc3R1ZGlvLmdpdGh1Yi5pby9ic2xpYi9yZWZlcmVuY2UvYnNfdGhlbWUuaHRtbA==">bslib::bs_theme()</span> 创建一个主题，然后使用页面布局函数的 <code>theme</code> 参数将其应用于应用程序：</p><figure class="highlight r"><figcaption data-lang="r"></figcaption><table><tr><td data-num="1"></td><td><pre>fluidPage<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="2"></td><td><pre>  theme <span class="token operator">=</span> bslib<span class="token operator">::</span>bs_theme<span class="token punctuation">(</span><span class="token ellipsis">...</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="3"></td><td><pre><span class="token punctuation">)</span></pre></td></tr></table></figure><p>如果不特别指定，Shiny 将使用其自创建以来基本上使用的经典 Bootstrap v3 主题。默认情况下， <code>bslib::bs_theme()</code> 将使用 Bootstrap v4。如果您只使用内置组件，使用 Bootstrap v4 替代 v3 不会造成问题。如果您使用了自定义 HTML，它可能会造成问题，因此您可以通过设置 <code>version = 3</code> 来强制它保持 v3。</p><h3 id="652-shiny主题"><a class="anchor" href="#652-shiny主题">#</a> 6.5.2 Shiny 主题</h3><p>更改应用程序整体外观的最简单方法是使用 <code>bootswatch</code> 参数对 <code>bslib::bs_theme()</code> 选择一个预先制作的 <code>bootswatch</code> 主题。图 6.9 显示了以下代码的结果，切换其他主题为 “darkly”。</p><figure class="highlight r"><figcaption data-lang="r"></figcaption><table><tr><td data-num="1"></td><td><pre>ui <span class="token operator">&lt;-</span> fluidPage<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="2"></td><td><pre>  theme <span class="token operator">=</span> bslib<span class="token operator">::</span>bs_theme<span class="token punctuation">(</span>bootswatch <span class="token operator">=</span> <span class="token string">"darkly"</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="3"></td><td><pre>  sidebarLayout<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="4"></td><td><pre>    sidebarPanel<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="5"></td><td><pre>      textInput<span class="token punctuation">(</span><span class="token string">"txt"</span><span class="token punctuation">,</span> <span class="token string">"Text input:"</span><span class="token punctuation">,</span> <span class="token string">"text here"</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="6"></td><td><pre>      sliderInput<span class="token punctuation">(</span><span class="token string">"slider"</span><span class="token punctuation">,</span> <span class="token string">"Slider input:"</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">100</span><span class="token punctuation">,</span> <span class="token number">30</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="7"></td><td><pre>    <span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="8"></td><td><pre>    mainPanel<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="9"></td><td><pre>      h1<span class="token punctuation">(</span>paste0<span class="token punctuation">(</span><span class="token string">"Theme: darkly"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="10"></td><td><pre>      h2<span class="token punctuation">(</span><span class="token string">"Header 2"</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="11"></td><td><pre>      p<span class="token punctuation">(</span><span class="token string">"Some text"</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="12"></td><td><pre>    <span class="token punctuation">)</span></pre></td></tr><tr><td data-num="13"></td><td><pre>  <span class="token punctuation">)</span></pre></td></tr><tr><td data-num="14"></td><td><pre><span class="token punctuation">)</span></pre></td></tr></table></figure><p><img data-src="https://d33wubrfki0l68.cloudfront.net/6850c18bfcfd5671f12f1f638c2c76b4ccb5b11d/07f6a/demos/action-layout/theme-flatly.png" alt="图6.9 相同的app采用了用四个bootswatch主题风格：darkly、flatly、sandstone和united"></p><p>此外，你可以利用 <code>bs_theme()</code> 的其他参数创建自己的主题，如 <code>bg</code> （背景颜色）， <code>fg</code> （前景色）和 <code>base_font</code> ：</p><figure class="highlight r"><figcaption data-lang="r"></figcaption><table><tr><td data-num="1"></td><td><pre>theme <span class="token operator">&lt;-</span> bslib<span class="token operator">::</span>bs_theme<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="2"></td><td><pre>  bg <span class="token operator">=</span> <span class="token string">"#0b3d91"</span><span class="token punctuation">,</span> </pre></td></tr><tr><td data-num="3"></td><td><pre>  fg <span class="token operator">=</span> <span class="token string">"white"</span><span class="token punctuation">,</span> </pre></td></tr><tr><td data-num="4"></td><td><pre>  base_font <span class="token operator">=</span> <span class="token string">"Source Sans Pro"</span></pre></td></tr><tr><td data-num="5"></td><td><pre><span class="token punctuation">)</span></pre></td></tr></table></figure><p>一种预览和自定义主题的简单方法是使用 <code>bslib::bs_theme_preview(theme)</code> 。这将打开一个 Shiny 应用程序，展示该主题在应用于许多标准控件时的外观，同时还为你提供交互式控件，用于自定义最重要的参数。</p><h3 id="653-图表主题"><a class="anchor" href="#653-图表主题">#</a> 6.5.3 图表主题</h3><p>如果你已经对你的应用程序样式进行了大量自定义，你可能还想自定义图表以匹配整体风格。幸运的是，这非常简单，多亏了<span class="exturl" data-url="aHR0cHM6Ly9yc3R1ZGlvLmdpdGh1Yi5pby90aGVtYXRpYy8="> thematic</span> 包，它可以自动对 ggplot2、lattice 和基础图表进行主题化。只需在 server 函数中调用 <code>thematic_shiny()</code> 。这将自动确定你的应用程序主题的所有设置，如图 6.10 所示。</p><figure class="highlight r"><figcaption data-lang="r"></figcaption><table><tr><td data-num="1"></td><td><pre>library<span class="token punctuation">(</span>ggplot2<span class="token punctuation">)</span></pre></td></tr><tr><td data-num="2"></td><td><pre></pre></td></tr><tr><td data-num="3"></td><td><pre>ui <span class="token operator">&lt;-</span> fluidPage<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="4"></td><td><pre>  theme <span class="token operator">=</span> bslib<span class="token operator">::</span>bs_theme<span class="token punctuation">(</span>bootswatch <span class="token operator">=</span> <span class="token string">"darkly"</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="5"></td><td><pre>  titlePanel<span class="token punctuation">(</span><span class="token string">"A themed plot"</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="6"></td><td><pre>  plotOutput<span class="token punctuation">(</span><span class="token string">"plot"</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="7"></td><td><pre><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="8"></td><td><pre></pre></td></tr><tr><td data-num="9"></td><td><pre>server <span class="token operator">&lt;-</span> <span class="token keyword">function</span><span class="token punctuation">(</span>input<span class="token punctuation">,</span> output<span class="token punctuation">,</span> session<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span></pre></td></tr><tr><td data-num="10"></td><td><pre>  thematic<span class="token operator">::</span>thematic_shiny<span class="token punctuation">(</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="11"></td><td><pre>  </pre></td></tr><tr><td data-num="12"></td><td><pre>  output<span class="token operator">$</span>plot <span class="token operator">&lt;-</span> renderPlot<span class="token punctuation">(</span><span class="token punctuation">&#123;</span></pre></td></tr><tr><td data-num="13"></td><td><pre>    ggplot<span class="token punctuation">(</span>mtcars<span class="token punctuation">,</span> aes<span class="token punctuation">(</span>wt<span class="token punctuation">,</span> mpg<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">+</span></pre></td></tr><tr><td data-num="14"></td><td><pre>      geom_point<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span></pre></td></tr><tr><td data-num="15"></td><td><pre>      geom_smooth<span class="token punctuation">(</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="16"></td><td><pre>  <span class="token punctuation">&#125;</span><span class="token punctuation">,</span> res <span class="token operator">=</span> <span class="token number">96</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="17"></td><td><pre><span class="token punctuation">&#125;</span></pre></td></tr></table></figure><p><img data-src="https://d33wubrfki0l68.cloudfront.net/0e7243ec6ca6821445c04bff6488fcf612c3fe88/e378c/demos/action-layout/thematic.png" alt="图6.10 使用thematic::thematic_shiny()确保ggplot2自动匹配应用程序主题"></p><h3 id="654-练习"><a class="anchor" href="#654-练习">#</a> 6.5.4 练习</h3><p><strong>6.4.5.1</strong> 使用 <code>bslib::bs_theme_preview()</code> 制作你能想到的最丑的主题。</p><h2 id="66-面罩之下"><a class="anchor" href="#66-面罩之下">#</a> 6.6 面罩之下</h2><p>Shiny 的设计是为了让 R 用户不需要了解 HTML 的细节。但是，如果你知道一些 HTML 和 CSS，你仍然可以进一步定制 Shiny。不幸的是，教授 HTML 和 CSS 不在本书的范围内，但 MDN 的<span class="exturl" data-url="aHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9MZWFybi9HZXR0aW5nX3N0YXJ0ZWRfd2l0aF90aGVfd2ViL0hUTUxfYmFzaWNz"> HTML</span> 和<span class="exturl" data-url="aHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9MZWFybi9HZXR0aW5nX3N0YXJ0ZWRfd2l0aF90aGVfd2ViL0NTU19iYXNpY3M="> CSS</span> 基础教程是一个很好的起点。</p><p>最重要的是要知道，所有输入、输出和布局函数背后都没有魔法：它们只是生成 HTML。您可以通过在控制台中直接执行 UI 函数来查看 HTML：</p><figure class="highlight r"><figcaption data-lang="r"></figcaption><table><tr><td data-num="1"></td><td><pre>fluidPage<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="2"></td><td><pre>  textInput<span class="token punctuation">(</span><span class="token string">"name"</span><span class="token punctuation">,</span> <span class="token string">"What's your name?"</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="3"></td><td><pre><span class="token punctuation">)</span></pre></td></tr></table></figure><figure class="highlight html"><figcaption data-lang="HTML"></figcaption><table><tr><td data-num="1"></td><td><pre><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>container-fluid<span class="token punctuation">"</span></span><span class="token punctuation">></span></span></pre></td></tr><tr><td data-num="2"></td><td><pre>  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>form-group shiny-input-container<span class="token punctuation">"</span></span><span class="token punctuation">></span></span></pre></td></tr><tr><td data-num="3"></td><td><pre>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>label</span> <span class="token attr-name">for</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>name<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>What's your name?<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>label</span><span class="token punctuation">></span></span></pre></td></tr><tr><td data-num="4"></td><td><pre>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>name<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>text<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>form-control<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token punctuation">"</span></span><span class="token punctuation">/></span></span></pre></td></tr><tr><td data-num="5"></td><td><pre>  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span></pre></td></tr><tr><td data-num="6"></td><td><pre><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span></pre></td></tr></table></figure><p>请注意，这是 <code>&lt;body&gt;</code> 标签的内容；Shiny 的其他部分负责生成 <code>&lt;head&gt;</code> 。如果你想包含额外的 CSS 或 JS 依赖项，你需要学习 <span class="exturl" data-url="aHR0cHM6Ly9yZHJyLmlvL3BrZy9odG1sdG9vbHMvbWFuL2h0bWxEZXBlbmRlbmN5Lmh0bWw=">htmltools::htmlDependency()</span>。两个好的起点是 <span class="exturl" data-url="aHR0cHM6Ly9ibG9nLnItaHViLmlvLzIwMjAvMDgvMjUvanMtci8jd2ViLWRlcGVuZGVuY3ktbWFuYWdlbWVudA==">https://blog.r-hub.io/2020/08/25/js-r/#web-dependency-management</span> 和 <span class="exturl" data-url="aHR0cHM6Ly91bmxlYXNoLXNoaW55LnJpbnRlcmZhY2UuY29tL2h0bWx0b29scy1kZXBlbmRlbmNpZXMuaHRtbA==">https://unleash-shiny.rinterface.com/htmltools-dependencies.html</span>。</p><p>可以将自己的 HTML 添加到 <code>ui</code> 。一种方法是通过 <span class="exturl" data-url="aHR0cHM6Ly9yZHJyLmlvL3BrZy9odG1sdG9vbHMvbWFuL0hUTUwuaHRtbA==">HTML()</span> 函数包含文本 HTML。在下面的例子中，我使用 “原始字符常量”， <code>r&quot;()&quot;</code> ，以便更容易在字符串中包含引号：</p><figure class="highlight r"><figcaption data-lang="r"></figcaption><table><tr><td data-num="1"></td><td><pre>ui <span class="token operator">&lt;-</span> fluidPage<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="2"></td><td><pre>  HTML<span class="token punctuation">(</span>r"<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="3"></td><td><pre>    <span class="token operator">&lt;</span>h1<span class="token operator">></span>This is a heading<span class="token operator">&lt;</span><span class="token operator">/</span>h1<span class="token operator">></span></pre></td></tr><tr><td data-num="4"></td><td><pre>    <span class="token operator">&lt;</span>p class<span class="token operator">=</span><span class="token string">"my-class"</span><span class="token operator">></span>This is some text<span class="token operator">!</span><span class="token operator">&lt;</span><span class="token operator">/</span>p<span class="token operator">></span></pre></td></tr><tr><td data-num="5"></td><td><pre>    <span class="token operator">&lt;</span>ul<span class="token operator">></span></pre></td></tr><tr><td data-num="6"></td><td><pre>      <span class="token operator">&lt;</span>li<span class="token operator">></span>First bullet<span class="token operator">&lt;</span><span class="token operator">/</span>li<span class="token operator">></span></pre></td></tr><tr><td data-num="7"></td><td><pre>      <span class="token operator">&lt;</span>li<span class="token operator">></span>Second bullet<span class="token operator">&lt;</span><span class="token operator">/</span>li<span class="token operator">></span></pre></td></tr><tr><td data-num="8"></td><td><pre>    <span class="token operator">&lt;</span><span class="token operator">/</span>ul<span class="token operator">></span></pre></td></tr><tr><td data-num="9"></td><td><pre>  <span class="token punctuation">)</span>"<span class="token punctuation">)</span></pre></td></tr><tr><td data-num="10"></td><td><pre><span class="token punctuation">)</span></pre></td></tr></table></figure><p>如果您是 HTML/CSS 专家，您可能想知道是否可以完全跳过 <code>fluidPage()</code> 并提供原始 HTML。有关更多详细信息，请参阅 “<span class="exturl" data-url="aHR0cHM6Ly9zaGlueS5yc3R1ZGlvLmNvbS9hcnRpY2xlcy9odG1sLXVpLmh0bWw=">使用 HTML 构建整个 UI</span>”。</p><p>或者，您可以使用 Shiny 提供的 HTML 辅助函数。对于最重要的元素，如 <code>h1()</code> 和 <code>p()</code> ，有常规函数，所有其他元素都可以通过其他标签辅助函数访问。命名参数成为属性，未命名参数成为子元素，因此我们可以将上面的 HTML 重新创建为：</p><figure class="highlight r"><figcaption data-lang="r"></figcaption><table><tr><td data-num="1"></td><td><pre>ui <span class="token operator">&lt;-</span> fluidPage<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="2"></td><td><pre>  h1<span class="token punctuation">(</span><span class="token string">"This is a heading"</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="3"></td><td><pre>  p<span class="token punctuation">(</span><span class="token string">"This is some text"</span><span class="token punctuation">,</span> class <span class="token operator">=</span> <span class="token string">"my-class"</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="4"></td><td><pre>  tags<span class="token operator">$</span>ul<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="5"></td><td><pre>    tags<span class="token operator">$</span>li<span class="token punctuation">(</span><span class="token string">"First bullet"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> </pre></td></tr><tr><td data-num="6"></td><td><pre>    tags<span class="token operator">$</span>li<span class="token punctuation">(</span><span class="token string">"Second bullet"</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="7"></td><td><pre>  <span class="token punctuation">)</span></pre></td></tr><tr><td data-num="8"></td><td><pre><span class="token punctuation">)</span></pre></td></tr></table></figure><p>使用代码生成 HTML 的一个优点是，你可以将现有的 Shiny 组件交织到自定义结构中。例如，以下代码生成了一段包含两个输出的文本段落，其中一个为粗体：</p><figure class="highlight r"><figcaption data-lang="r"></figcaption><table><tr><td data-num="1"></td><td><pre>tags<span class="token operator">$</span>p<span class="token punctuation">(</span></pre></td></tr><tr><td data-num="2"></td><td><pre>  <span class="token string">"You made "</span><span class="token punctuation">,</span> </pre></td></tr><tr><td data-num="3"></td><td><pre>  tags<span class="token operator">$</span>b<span class="token punctuation">(</span><span class="token string">"$"</span><span class="token punctuation">,</span> textOutput<span class="token punctuation">(</span><span class="token string">"amount"</span><span class="token punctuation">,</span> inline <span class="token operator">=</span> <span class="token boolean">TRUE</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="4"></td><td><pre>  <span class="token string">" in the last "</span><span class="token punctuation">,</span> </pre></td></tr><tr><td data-num="5"></td><td><pre>  textOutput<span class="token punctuation">(</span><span class="token string">"days"</span><span class="token punctuation">,</span> inline <span class="token operator">=</span> <span class="token boolean">TRUE</span><span class="token punctuation">)</span><span class="token punctuation">,</span></pre></td></tr><tr><td data-num="6"></td><td><pre>  <span class="token string">" days "</span> </pre></td></tr><tr><td data-num="7"></td><td><pre><span class="token punctuation">)</span></pre></td></tr></table></figure><p>请注意使用 <code>inline = TRUE</code> ； <code>textOutput()</code> 默认是生成一个完整的段落。</p><p>要了解更多关于使用 HTML、CSS 和 JavaScript 制作引人注目的用户界面的知识，我强烈推荐 David Granjon 的<span class="exturl" data-url="aHR0cHM6Ly91bmxlYXNoLXNoaW55LnJpbnRlcmZhY2UuY29tL2luZGV4Lmh0bWw=">《Shiny 的杰出用户界面》</span>。</p><h2 id="67-总结"><a class="anchor" href="#67-总结">#</a> 6.7 总结</h2><p>本章为你提供了制作复杂而吸引人的 Shiny 应用程序所需的工具。你已经学习了 Shiny 函数，这些函数允许你布局单页和多页应用程序（如 <code>fluidPage()</code> 和 <code>tabsetPanel()</code> ），以及如何使用主题定制整体视觉外观。你还学到了一些关于底层的东西：你知道 Shiny 使用 Bootstrap，并且输入和输出函数只返回 HTML，你也可以自己创建自己的 HTML。</p><p>在下一章中，您将了解有关应用程序中另一个重要视觉组件的更多信息：图形。</p><h1 id="加关注"><a class="anchor" href="#加关注">#</a> 加关注</h1><p>关注公众号 “生信之巅”。</p><table align="center"><tr><td align="center"><img data-src="https://cdn.jsdelivr.net/gh/liaochenlanruo/cdn@master/img/social/生信之巅公众号.jpg" alt="生信之巅微信公众号" style="width:100px;height:100px;vertical-align:-20px;border-radius:0;margin-right:0;margin-bottom:5px;align:center"></td><td align="center"><img data-src="https://cdn.jsdelivr.net/gh/liaochenlanruo/cdn@master/img/social/小程序码.png" alt="生信之巅小程序码" style="width:100px;height:100px;vertical-align:-20px;border-radius:0;margin-left:0;margin-bottom:5px;align:center"></td></tr></table><p><font color="#FF0000"><ruby><b>敬告</b>：使用文中脚本请引用本文网址，请尊重本人的劳动成果，谢谢！<rt><b>Notice</b>: When you use the scripts in this article, please cite the link of this webpage. Thank you!</rt></ruby></font></p><div class="tags"><a href="/tags/%E7%BC%96%E7%A8%8B/" rel="tag"><i class="ic i-tag"></i> 编程</a> <a href="/tags/Shiny%E5%85%A5%E9%97%A8%E7%B3%BB%E5%88%97/" rel="tag"><i class="ic i-tag"></i> Shiny入门系列</a></div></div><footer><div class="meta"><span class="item"><span class="icon"><i class="ic i-calendar-check"></i> </span><span class="text">Edited on</span> <time title="Modified: 2024-01-25 09:16:52" itemprop="dateModified" datetime="2024-01-25T09:16:52+08:00">2024-01-25</time> </span><span id="post/6718.html" class="item leancloud_visitors" data-flag-title="Shiny从入门到入定——6-布局、主题、HTML" title="Views"><span class="icon"><i class="ic i-eye"></i> </span><span class="text">Views</span> <span class="leancloud-visitors-count"></span> <span class="text">times</span></span></div><div class="reward"><button><i class="ic i-heartbeat"></i> Donate</button><p>Give me a cup of [coffee]~(￣▽￣)~*</p><div id="qr"><div><img data-src="/images/reward-wepays.jpg" alt="Hualin Liu WeChat Pay"><p>WeChat Pay</p></div><div><img data-src="/images/AliPays.jpg" alt="Hualin Liu Alipay"><p>Alipay</p></div></div></div><div id="copyright"><ul><li class="author"><strong>Post author: </strong>liaochenlanruo <i class="ic i-at"><em>@</em></i>了尘兰若的小坑</li><li class="link"><strong>Post link: </strong><a href="https://liaochenlanruo.gitee.io/post/6718.html" title="Shiny从入门到入定——6-布局、主题、HTML">https://liaochenlanruo.gitee.io/post/6718.html</a></li><li class="license"><strong>Copyright Notice: </strong>All articles in this blog are licensed under <span class="exturl" data-url="aHR0cHM6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLXNhLzQuMC9kZWVkLnpo"><i class="ic i-creative-commons"><em>(CC)</em></i>BY-NC-SA</span> unless stating additionally.</li></ul></div></footer></article></div><div class="post-nav"><div class="item left"><a href="/post/83c3.html" itemprop="url" rel="prev" data-background-image="https:&#x2F;&#x2F;cdn.jsdelivr.net&#x2F;gh&#x2F;liaochenlanruo&#x2F;cdn@master&#x2F;img&#x2F;custom&#x2F;bgs&#x2F;thumb_205.webp" title="Shiny从入门到入定——5-工作流"><span class="type">Previous Post</span> <span class="category"><i class="ic i-flag"></i> IT</span><h3>Shiny从入门到入定——5-工作流</h3></a></div><div class="item right"><a href="/post/6685.html" itemprop="url" rel="next" data-background-image="https:&#x2F;&#x2F;cdn.jsdelivr.net&#x2F;gh&#x2F;liaochenlanruo&#x2F;cdn@master&#x2F;img&#x2F;custom&#x2F;bgs&#x2F;thumb_207.webp" title="Shiny从入门到入定——7-图形"><span class="type">Next Post</span> <span class="category"><i class="ic i-flag"></i> IT</span><h3>Shiny从入门到入定——7-图形</h3></a></div></div><div class="wrap" id="comments"></div></div><div id="sidebar"><div class="inner"><div class="panels"><div class="inner"><div class="contents panel pjax" data-title="Contents"><ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#6-%E5%B8%83%E5%B1%80%E4%B8%BB%E9%A2%98html"><span class="toc-number">1.</span> <span class="toc-text">6 布局，主题，HTML</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#61-%E5%89%8D%E8%A8%80"><span class="toc-number">1.1.</span> <span class="toc-text">6.1 前言</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#62-%E5%8D%95%E9%A1%B5%E5%B8%83%E5%B1%80"><span class="toc-number">1.2.</span> <span class="toc-text">6.2 单页布局</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#621-%E9%A1%B5%E9%9D%A2%E5%8A%9F%E8%83%BD"><span class="toc-number">1.2.1.</span> <span class="toc-text">6.2.1 页面功能</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#622-%E5%B8%A6%E4%BE%A7%E8%BE%B9%E6%A0%8F%E7%9A%84%E9%A1%B5%E9%9D%A2"><span class="toc-number">1.2.2.</span> <span class="toc-text">6.2.2 带侧边栏的页面</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#623-%E5%A4%9A%E8%A1%8C"><span class="toc-number">1.2.3.</span> <span class="toc-text">6.2.3 多行</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#624-%E7%BB%83%E4%B9%A0"><span class="toc-number">1.2.4.</span> <span class="toc-text">6.2.4 练习</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#63-%E5%A4%9A%E9%A1%B5%E5%B8%83%E5%B1%80"><span class="toc-number">1.3.</span> <span class="toc-text">6.3 多页布局</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#631-%E9%80%89%E9%A1%B9%E5%8D%A1%E9%9B%86"><span class="toc-number">1.3.1.</span> <span class="toc-text">6.3.1 选项卡集</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#632-%E5%AF%BC%E8%88%AA%E5%88%97%E8%A1%A8%E5%92%8C%E5%AF%BC%E8%88%AA%E6%A0%8F"><span class="toc-number">1.3.2.</span> <span class="toc-text">6.3.2 导航列表和导航栏</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#64-%E5%BC%95%E5%AF%BC%E7%A8%8B%E5%BA%8Fbootstrap"><span class="toc-number">1.4.</span> <span class="toc-text">6.4 引导程序（Bootstrap）</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#65-%E4%B8%BB%E9%A2%98"><span class="toc-number">1.5.</span> <span class="toc-text">6.5 主题</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#651-%E5%BC%80%E5%A7%8B"><span class="toc-number">1.5.1.</span> <span class="toc-text">6.5.1 开始</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#652-shiny%E4%B8%BB%E9%A2%98"><span class="toc-number">1.5.2.</span> <span class="toc-text">6.5.2 Shiny 主题</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#653-%E5%9B%BE%E8%A1%A8%E4%B8%BB%E9%A2%98"><span class="toc-number">1.5.3.</span> <span class="toc-text">6.5.3 图表主题</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#654-%E7%BB%83%E4%B9%A0"><span class="toc-number">1.5.4.</span> <span class="toc-text">6.5.4 练习</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#66-%E9%9D%A2%E7%BD%A9%E4%B9%8B%E4%B8%8B"><span class="toc-number">1.6.</span> <span class="toc-text">6.6 面罩之下</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#67-%E6%80%BB%E7%BB%93"><span class="toc-number">1.7.</span> <span class="toc-text">6.7 总结</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E5%8A%A0%E5%85%B3%E6%B3%A8"><span class="toc-number">2.</span> <span class="toc-text">加关注</span></a></li></ol></div><div class="related panel pjax" data-title="Related"><ul><li><a href="/post/10103.html" rel="bookmark" title="perl循环调用python爬虫批量下载喜马拉雅音频">perl循环调用python爬虫批量下载喜马拉雅音频</a></li><li><a href="/post/2159.html" rel="bookmark" title="syncthing搭建自己的同步云网盘">syncthing搭建自己的同步云网盘</a></li><li><a href="/post/50435.html" rel="bookmark" title="JAVA jre 安装或升级1603 error解决办法">JAVA jre 安装或升级1603 error解决办法</a></li><li><a href="/post/aa20.html" rel="bookmark" title="获取下一版本的内部预览版windows系统">获取下一版本的内部预览版windows系统</a></li><li><a href="/post/c78e.html" rel="bookmark" title="windows 10 中文乱码解决方案">windows 10 中文乱码解决方案</a></li><li><a href="/post/6bf1.html" rel="bookmark" title="Ubuntu open-mpi运行错误">Ubuntu open-mpi运行错误</a></li><li><a href="/post/f1a4.html" rel="bookmark" title="Github操作">Github操作</a></li><li><a href="/post/f298.html" rel="bookmark" title="Wget 技巧">Wget 技巧</a></li><li><a href="/post/16e1.html" rel="bookmark" title="Perl捕获外部命令执行异常并继续运行后续代码">Perl捕获外部命令执行异常并继续运行后续代码</a></li><li><a href="/post/9092.html" rel="bookmark" title="Perl获取外部命令执行结果的输出">Perl获取外部命令执行结果的输出</a></li><li><a href="/post/9d1b.html" rel="bookmark" title="Linux骚操作">Linux骚操作</a></li><li><a href="/post/3f45.html" rel="bookmark" title="Perl处理可恶的Windows换行符">Perl处理可恶的Windows换行符</a></li><li><a href="/post/893d.html" rel="bookmark" title="命令模式下配置Linux网络">命令模式下配置Linux网络</a></li><li><a href="/post/ed43.html" rel="bookmark" title="Linux中使用tar将大文件压缩为多个小的压缩包">Linux中使用tar将大文件压缩为多个小的压缩包</a></li><li><a href="/post/54a0.html" rel="bookmark" title="WSL安装Docker避坑指北">WSL安装Docker避坑指北</a></li><li><a href="/post/4b9c.html" rel="bookmark" title="Shiny从入门到入定——0欢迎入坑">Shiny从入门到入定——0欢迎入坑</a></li><li><a href="/post/b376.html" rel="bookmark" title="Shiny从入门到入定——1.在小小的花园里面挖呀挖呀挖">Shiny从入门到入定——1.在小小的花园里面挖呀挖呀挖</a></li><li><a href="/post/5369.html" rel="bookmark" title="Shiny从入门到入定——2-在大大的花园里面挖呀挖呀挖">Shiny从入门到入定——2-在大大的花园里面挖呀挖呀挖</a></li><li><a href="/post/41c3.html" rel="bookmark" title="Shiny从入门到入定——3-在特别大的花园里面挖呀挖呀挖">Shiny从入门到入定——3-在特别大的花园里面挖呀挖呀挖</a></li><li><a href="/post/377b.html" rel="bookmark" title="Shiny从入门到入定——4-挖坑完毕之案例研究">Shiny从入门到入定——4-挖坑完毕之案例研究</a></li><li><a href="/post/83c3.html" rel="bookmark" title="Shiny从入门到入定——5-工作流">Shiny从入门到入定——5-工作流</a></li><li class="active"><a href="/post/6718.html" rel="bookmark" title="Shiny从入门到入定——6-布局、主题、HTML">Shiny从入门到入定——6-布局、主题、HTML</a></li><li><a href="/post/6685.html" rel="bookmark" title="Shiny从入门到入定——7-图形">Shiny从入门到入定——7-图形</a></li><li><a href="/post/6561.html" rel="bookmark" title="Shiny从入门到入定——8-用户反馈">Shiny从入门到入定——8-用户反馈</a></li><li><a href="/post/72d6.html" rel="bookmark" title="Shiny从入门到入定——9-上传和下载">Shiny从入门到入定——9-上传和下载</a></li><li><a href="/post/e6be.html" rel="bookmark" title="Shiny从入门到入定——10-动态UI">Shiny从入门到入定——10-动态UI</a></li><li><a href="/post/8eca.html" rel="bookmark" title="Shiny从入门到入定——11-书签">Shiny从入门到入定——11-书签</a></li><li><a href="/post/3709.html" rel="bookmark" title="Shiny从入门到入定——12-Tidy evaluation">Shiny从入门到入定——12-Tidy evaluation</a></li><li><a href="/post/5e3d.html" rel="bookmark" title="Shiny从入门到入定——13-Why reactivity?">Shiny从入门到入定——13-Why reactivity?</a></li><li><a href="/post/43fc.html" rel="bookmark" title="深入理解特征标准化：为何、如何及其重要性">深入理解特征标准化：为何、如何及其重要性</a></li></ul></div><div class="overview panel" data-title="Overview"><div class="author" itemprop="author" itemscope itemtype="http://schema.org/Person"><img class="image" itemprop="image" alt="Hualin Liu" data-src="/images/head.jpg"><p class="name" itemprop="name">Hualin Liu</p><div class="description" itemprop="description">分享微生物生物信息学分析方法，欢迎加入QQ群交流945751012，不接受群内广告！</div></div><nav class="state"><div class="item posts"><a href="/archives/"><span class="count">130</span> <span class="name">posts</span></a></div><div class="item categories"><a href="/categories/"><span class="count">12</span> <span class="name">categories</span></a></div><div class="item tags"><a href="/tags/"><span class="count">54</span> <span class="name">tags</span></a></div></nav><div class="social"><span class="exturl item github" data-url="aHR0cDovL2dpdGh1Yi5jb20vbGlhb2NoZW5sYW5ydW8=" title="http:&#x2F;&#x2F;github.com&#x2F;liaochenlanruo"><i class="ic i-github"></i></span> <span class="exturl item zhihu" data-url="aHR0cHM6Ly93d3cuemhpaHUuY29tL3Blb3BsZS9zdWFuLWxhLW1pYW4tcGlhbi10YW5nLWNpdW0=" title="https:&#x2F;&#x2F;www.zhihu.com&#x2F;people&#x2F;suan-la-mian-pian-tang-cium"><i class="ic i-zhihu"></i></span> <span class="exturl item weibo" data-url="aHR0cHM6Ly93ZWliby5jb20vdS8yNzE1MjEwOTIz" title="https:&#x2F;&#x2F;weibo.com&#x2F;u&#x2F;2715210923"><i class="ic i-weibo"></i></span> <span class="exturl item about" data-url="aHR0cHM6Ly93d3cubGlhb2NoZW5sYW5ydW8uZnVuL2Fib3V0" title="https:&#x2F;&#x2F;www.liaochenlanruo.fun&#x2F;about"><i class="ic i-address-card"></i></span> <span class="exturl item email" data-url="bWFpbHRvOmxpYW9jaGVubGFucnVvQHdlYm1haWwuaHphdS5lZHUuY24=" title="mailto:liaochenlanruo@webmail.hzau.edu.cn"><i class="ic i-envelope"></i></span> <span class="exturl item douban" data-url="aHR0cHM6Ly93d3cuZG91YmFuLmNvbS9wZW9wbGUvbGlhb2NoZW5sYW5ydW8vP19pPTczNDYxMjVRalo1QjZWLw==" title="https:&#x2F;&#x2F;www.douban.com&#x2F;people&#x2F;liaochenlanruo&#x2F;?_i&#x3D;7346125QjZ5B6V&#x2F;"><i class="ic i-douban"></i></span> <span class="exturl item google" data-url="aHR0cHM6Ly9zY2hvbGFyLmdvb2dsZS5jby5qcC9jaXRhdGlvbnM/dXNlcj1YYW9STk1RQUFBQUomaGw9amE=" title="https:&#x2F;&#x2F;scholar.google.co.jp&#x2F;citations?user&#x3D;XaoRNMQAAAAJ&amp;hl&#x3D;ja"><i class="ic i-google"></i></span></div><ul class="menu"><li class="item"><a href="/" rel="section"><i class="ic i-home"></i>Home</a></li><li class="item dropdown"><a href="javascript:void(0);"><i class="ic i-user"></i>About</a><ul class="submenu"><li class="item"><a href="/about/" rel="section"><i class="ic i-user"></i>About me</a></li><li class="item"><a href="/comment/" rel="section"><i class="ic i-envelope"></i>Comment</a></li></ul></li><li class="item dropdown"><a href="javascript:void(0);"><i class="ic i-feather"></i>Posts</a><ul class="submenu"><li class="item"><a href="/archives/" rel="section"><i class="ic i-list-alt"></i>Archives</a></li><li class="item"><a href="/categories/" rel="section"><i class="ic i-th"></i>Categories</a></li><li class="item"><a href="/tags/" rel="section"><i class="ic i-tags"></i>Tags</a></li></ul></li><li class="item dropdown"><a href="javascript:void(0);"><i class="ic i-list-ol"></i>List</a><ul class="submenu"><li class="item"><a href="/photos/" rel="section"><i class="ic i-person"></i>Photos</a></li><li class="item"><a href="/skip/gallery/" rel="section"><i class="ic i-cloud"></i>Gallery</a></li><li class="item"><a href="/skip/box/" rel="section"><i class="ic i-magic"></i>Box</a></li><li class="item"><span class="exturl" data-url="aHR0cHM6Ly9saWFvY2hlbmxhbnJ1by5mdW4vcmVmZXJlbmNlLw=="><i class="ic i-th"></i>cheatsheets</span></li></ul></li><li class="item"><a href="/donate/" rel="section"><i class="ic i-coffee"></i>Donate</a></li><li class="item"><a href="/friends/" rel="section"><i class="ic i-heart"></i>Friends</a></li><li class="item"><span class="exturl" data-url="aHR0cHM6Ly9saWFvY2hlbmxhbnJ1by5naXRodWIuaW8="><i class="ic i-external-link-alt"></i>中文版</span></li><li class="item"><span class="exturl" data-url="aHR0cHM6Ly90cmF2ZWxsaW5ncy5saW5r"><i class="ic i-forward"></i>Travelling</span></li></ul></div></div></div><ul id="quick"><li class="prev pjax"><a href="/post/83c3.html" rel="prev" title="Previous Post"><i class="ic i-chevron-left"></i></a></li><li class="up"><i class="ic i-arrow-up"></i></li><li class="down"><i class="ic i-arrow-down"></i></li><li class="next pjax"><a href="/post/6685.html" rel="next" title="Next Post"><i class="ic i-chevron-right"></i></a></li><li class="percent"></li></ul></div></div><div class="dimmer"></div></div></main><footer id="footer"><div class="inner"><div class="widgets"></div><div class="status"><div class="copyright">&copy; 2018 – <span itemprop="copyrightYear">2024</span> <span class="with-love"><i class="ic i-sakura rotate"></i> </span><span class="author" itemprop="copyrightHolder">Hualin Liu @ ResearchGo</span></div><div class="count"><span class="post-meta-item-icon"><i class="ic i-chart-area"></i> </span><span title="Symbols count total">788k words</span> <span class="post-meta-divider">|</span> <span class="post-meta-item-icon"><i class="ic i-coffee"></i> </span><span title="Reading time total">11:57</span><script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script><span class="post-meta-divider">|</span> <span class="post-meta-item-icon"><i class="ic i-info-circle"></i> </span><span style="padding-left:1px"><span id="busuanzi_container_site_pv">Total visits: <span id="busuanzi_value_site_pv" style="color:#f99"></span> times</span> <span class="post-meta-divider">|</span> <span class="post-meta-item-icon"><i class="ic i-user"></i> </span><span style="padding-left:1px"><span id="busuanzi_container_site_uv">Total visitors: <span id="busuanzi_value_site_uv" style="color:#f99"></span> people</span></span></span></div><div class="powered-by">Powered by <span class="exturl" data-url="aHR0cHM6Ly9oZXhvLmlv">Hexo</span> & Theme.<span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL2FtZWhpbWUvaGV4by10aGVtZS1zaG9rYQ==">Shoka</span></div></div></div></footer></div><script data-config type="text/javascript">var LOCAL={path:"post/6718.html",favicon:{show:"（●´3｀●）Goooood",hide:"(´Д｀)Booooom"},search:{placeholder:"Search for Posts",empty:"We didn't find any results for the search: ${query}",stats:"${hits} results found in ${time} ms"},valine:!0,fancybox:!0,copyright:'Copied to clipboard successfully! <br> All articles in this blog are licensed under <i class="ic i-creative-commons"></i>BY-NC-SA.',ignores:[function(e){return e.includes("#")},function(e){return new RegExp(LOCAL.path+"$").test(e)}]}</script><script src="https://cdn.polyfill.io/v2/polyfill.js"></script><script src="//cdn.jsdelivr.net/combine/npm/pace-js@1.0.2/pace.min.js,npm/pjax@0.2.8/pjax.min.js,npm/whatwg-fetch@3.4.0/dist/fetch.umd.min.js,npm/animejs@3.2.0/lib/anime.min.js,npm/algoliasearch@4/dist/algoliasearch-lite.umd.js,npm/instantsearch.js@4/dist/instantsearch.production.min.js,npm/lozad@1/dist/lozad.min.js,npm/quicklink@2/dist/quicklink.umd.js"></script><script src="/js/app.js?v=0.2.5"></script><script data-pjax>var _hmt=_hmt||[];!function(){var e=document.createElement("script");e.src="https://hm.baidu.com/hm.js?d211830a796ceefb38a141fde14e4d5a";var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t)}()</script></body></html>